﻿using System;
using System.Text;
using System.Collections.Generic;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using SpeakupBackend.Themes;
using SpeakupBackend.Classes;
using TableParsers;

namespace SpeakupTests.SpeakupBackend.Themes.Club
{
    [TestClass]
    public class ClubThemeTests
    {
        List<String> ThemeNames = new  List<string>{ "Club - name1", "Club - name2", "Club - name3" };


        [TestMethod]
        public void Create()
        {
            foreach (String name in ThemeNames)
            {
                foreach (ClubLevelGroup lg in ClubLevelGroup.ClubFactory.GetLevelGroups())
                {
                    ClubTheme theme = new ClubTheme(name, lg);

                    Assert.AreEqual(name, theme.Name);
                    Assert.AreEqual(lg, theme.LevelGroup);
                }
            }
        }

        [TestMethod]
        public void ObjectEquals()
        {
            ClubLevelGroup levelGroup = ClubLevelGroup.ClubFactory.GetLevelGroups().First();
            foreach (String nameLeft in ThemeNames)
            {
                foreach (String nameRight in ThemeNames)
                {
                    Object left = new ClubTheme(nameLeft, levelGroup);
                    Object right = new ClubTheme(nameRight, levelGroup);

                    Assert.AreEqual(left.Equals(right), nameLeft == nameRight);
                    Assert.AreEqual(right.Equals(left), nameLeft == nameRight);
                }
            }

            string name = ThemeNames.First();
            foreach (ClubLevelGroup leftLg in ClubLevelGroup.ClubFactory.GetLevelGroups())
            {
                foreach (ClubLevelGroup rightLg in ClubLevelGroup.ClubFactory.GetLevelGroups())
                {
                    Object left = new ClubTheme(name, leftLg);
                    Object right = new ClubTheme(name, rightLg);

                    Assert.AreEqual(left.Equals(right), leftLg == rightLg);
                    Assert.AreEqual(right.Equals(left), leftLg == rightLg);
                }
            }

        }

        [TestMethod]
        public void Equals()
        {
            ClubLevelGroup levelGroup = ClubLevelGroup.ClubFactory.GetLevelGroups().First();
            foreach (String nameLeft in ThemeNames)
            {
                foreach (String nameRight in ThemeNames)
                {
                    ClubTheme left = new ClubTheme(nameLeft, levelGroup);
                    ClubTheme right = new ClubTheme(nameRight, levelGroup);

                    Assert.AreEqual(left.Equals(right), nameLeft == nameRight);
                    Assert.AreEqual(right.Equals(left), nameLeft == nameRight);
                }
            }

            string name = ThemeNames.First();
            foreach (ClubLevelGroup leftLg in ClubLevelGroup.ClubFactory.GetLevelGroups())
            {
                foreach (ClubLevelGroup rightLg in ClubLevelGroup.ClubFactory.GetLevelGroups())
                {
                    ClubTheme left = new ClubTheme(name, leftLg);
                    ClubTheme right = new ClubTheme(name, rightLg);

                    Assert.AreEqual(left.Equals(right), leftLg == rightLg);
                    Assert.AreEqual(right.Equals(left), leftLg == rightLg);
                }
            }
        }

        [TestMethod]
        public new void GetHashCode()
        {
            ClubLevelGroup levelGroup = ClubLevelGroup.ClubFactory.GetLevelGroups().First();
            foreach (String nameLeft in ThemeNames)
            {
                foreach (String nameRight in ThemeNames)
                {
                    ClubTheme left = new ClubTheme(nameLeft, levelGroup);
                    ClubTheme right = new ClubTheme(nameRight, levelGroup);

                    Assert.AreEqual(left.GetHashCode() ==  right.GetHashCode(), nameLeft == nameRight);                   
                }
            }

            string name = ThemeNames.First();
            foreach (ClubLevelGroup leftLg in ClubLevelGroup.ClubFactory.GetLevelGroups())
            {
                foreach (ClubLevelGroup rightLg in ClubLevelGroup.ClubFactory.GetLevelGroups())
                {
                    ClubTheme left = new ClubTheme(name, leftLg);
                    ClubTheme right = new ClubTheme(name, rightLg);

                    Assert.AreEqual(left.GetHashCode() == right.GetHashCode(), leftLg == rightLg);                   
                }
            }
        }

        [TestMethod]
        public void CompareTo()
        {
            String  name = ThemeNames.First();

            foreach (ClubLevelGroup leftLg in ClubLevelGroup.ClubFactory.GetLevelGroups())
            {
                foreach (ClubLevelGroup rightLg in ClubLevelGroup.ClubFactory.GetLevelGroups())
                {
                    ClubTheme leftTh = new ClubTheme(name, leftLg);
                    ClubTheme rightTh = new ClubTheme(name, rightLg);

                    Assert.AreEqual(
                        Math.Sign(leftTh.CompareTo(rightTh)),
                        Math.Sign(leftLg.CompareTo(rightLg)));

                    Assert.AreEqual(
                        Math.Sign(rightTh.CompareTo(leftTh)),
                        Math.Sign(rightLg.CompareTo(leftLg)));

                }
            }

            ClubLevelGroup levelGroup = ClubLevelGroup.ClubFactory.GetLevelGroups().First();

            foreach (String nLeft in ThemeNames)
            {
                foreach (String nRight in ThemeNames)
                {
                    ClubTheme leftTh = new ClubTheme(nLeft, levelGroup);
                    ClubTheme rightTh = new ClubTheme(nRight, levelGroup);

                    Assert.AreEqual(
                        Math.Sign(leftTh.CompareTo(rightTh)),
                        Math.Sign(nLeft.CompareTo(nRight)));

                    Assert.AreEqual(
                        Math.Sign(rightTh.CompareTo(leftTh)),
                        Math.Sign(nRight.CompareTo(nLeft)));
                }
            }
        }

        [TestMethod]
        public void CompareOperators()
        {
            String name = ThemeNames.First();

            foreach (ClubLevelGroup leftLg in ClubLevelGroup.ClubFactory.GetLevelGroups())
            {
                foreach (ClubLevelGroup rightLg in ClubLevelGroup.ClubFactory.GetLevelGroups())
                {
                    ClubTheme leftTh = new ClubTheme(name, leftLg);
                    ClubTheme rightTh = new ClubTheme(name, rightLg);

                    Assert.AreEqual(leftTh == rightTh, leftLg == rightLg);
                    Assert.AreEqual(leftTh != rightTh, leftLg != rightLg);
                    Assert.AreEqual(leftTh < rightTh, leftLg < rightLg);
                    Assert.AreEqual(leftTh <= rightTh, leftLg <= rightLg);
                    Assert.AreEqual(leftTh > rightTh, leftLg > rightLg);
                    Assert.AreEqual(leftTh >= rightTh, leftLg >= rightLg);
                }
            }

            ClubLevelGroup levelGroup = ClubLevelGroup.ClubFactory.GetLevelGroups().First();

            foreach (String nLeft in ThemeNames)
            {
                foreach (String nRight in ThemeNames)
                {
                    ClubTheme leftTh = new ClubTheme(nLeft, levelGroup);
                    ClubTheme rightTh = new ClubTheme(nRight, levelGroup);

                    Assert.AreEqual(leftTh == rightTh, nLeft == nRight);
                    Assert.AreEqual(leftTh != rightTh, nLeft != nRight);
                    Assert.AreEqual(leftTh < rightTh, nLeft.CompareTo(nRight) < 0);
                    Assert.AreEqual(leftTh <= rightTh, nLeft.CompareTo(nRight) <= 0);
                    Assert.AreEqual(leftTh > rightTh, nLeft.CompareTo(nRight) > 0);
                    Assert.AreEqual(leftTh >= rightTh, nLeft.CompareTo(nRight) >= 0);
                }
            }
        }

        Class CreateClass(String name, ClassType classType, Level level)
        {
            int unit = 0;
            if (level != null)
            {
                unit = level.GetUnits().First();
            }

            return new Class(0, new ClassName(name, name, classType),
                                new ClassTime(DateTime.Now, TimeSpan.FromHours(12), TimeSpan.FromHours(13)),
                                unit, ClassStatus.Cancelled, ClassAction.None);
        }

        [TestMethod]
        public void IsCompatibleClass()
        {
            ClubTheme theme = new ClubTheme(ThemeNames.First(), ClubLevelGroup.ClubFactory.GetLevelGroups().First());

            Class nullUnitClass = CreateClass(ThemeNames.First(), ClassType.Club, null);
            Assert.IsFalse(theme.IsCompatibleClass(nullUnitClass));
            
            foreach (ClubLevelGroup thLevelGroup in ClubLevelGroup.ClubFactory.GetLevelGroups() )
            {
                foreach (String thName in ThemeNames)
                {
                    theme = new ClubTheme(thName, thLevelGroup);

                    foreach (Level clLevel in Level.GetLevels())
                    {
                        foreach (String clName in ThemeNames)
                        {
                            foreach (ClassType clType in Enum.GetValues(typeof(ClassType)))
                            {
                                Class cl = CreateClass(clName, clType, clLevel);

                                Assert.AreEqual(theme.IsCompatibleClass(cl),
                                                thLevelGroup.ContainsLevel(clLevel) && 
                                                thName == clName &&
                                                clType == ClassType.Club);
                            }

                        }
                    }

                }
            }


        }
    }
}
